using System;
using System.IO;
using System.Security.Cryptography;

namespace Framework.Core.Cache
{
    /// <summary>
    ///     Only For Legacy : Use this class when you cache whithout override GetHashCode and Equals
    /// </summary>
    public class HashProviderForLegacy : IHashProvider
    {
        private readonly ISerializer serializer;

        public HashProviderForLegacy(ISerializer serializer)
        {
            this.serializer = serializer;
        }

        public HashProviderForLegacy()
            : this(new BinarySerializer())
        {
        }

        public virtual int Create(object o)
        {
            if (o == null)
            {
                return 0;
            }

            return IsLegacy(o) ? GetCacheKeyForReferenceType(o) : o.GetHashCode();
        }

        private static bool IsLegacy(object o)
        {
            return o.GetType().GetMethod("GetHashCode").DeclaringType != o.GetType();
        }

        private int GetCacheKeyForReferenceType(object o)
        {
            using (var stream = new MemoryStream())
            {
                serializer.Serialize(o, stream);

                using (var md5 = MD5.Create())
                {
                    var hash = md5.ComputeHash(stream.ToArray());

                    return Convert.ToBase64String(hash).GetHashCode();
                }
            }
        }
    }
}
